<!-- components/GlobalModal.vue -->
<template>
  <Teleport to="body">
    <Transition name="modal" @after-leave="handleAfterLeave">
      <div v-if="state.visible.value" class="modal-overlay" @click.self="handleOverlayClick">
        <div class="modal-container" :style="containerStyle">
          <!-- 头部 -->
          <div v-if="state.config.value.showHeader" class="modal-header">
            <h3>{{ state.config.value.title }}</h3>
            <button v-if="state.config.value.closable" class="close-btn" :disabled="isAnyButtonLoading" @click="handleClose">
              &times;
            </button>
          </div>

          <!-- 内容区域 -->
          <div class="modal-content" :class="{ 'no-header': !state.config.value.showHeader }">
            <!-- 自定义组件 -->
            <component
              :is="state.config.value.contentComponent"
              v-if="state.config.value.contentComponent"
              v-bind="state.config.value.componentProps || {}"
              @close="handleClose"
            />
            <!-- 普通文本内容 -->
            <div v-else-if="state.config.value.content" v-html="state.config.value.content"></div>
            <!-- 默认插槽 -->
            <slot v-else></slot>
          </div>

          <!-- 底部按钮 -->
          <div v-if="state.config.value.showFooter && state.config.value.buttons?.length" class="modal-footer">
            <button
              v-for="(btn, index) in state.config.value.buttons"
              :key="index"
              :class="['btn', `btn-${btn.type || 'default'}`, { 'btn-loading': btn.loading }]"
              :disabled="isAnyButtonLoading && !btn.loading"
              @click="handleButtonClick(btn, index)"
            >
              <span class="btn-text">{{ btn.text }}</span>
              <span v-if="btn.loading" class="btn-loading-spinner"></span>
            </button>
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<script setup lang="ts">
import { computed, watch } from 'vue'
import { getModalState } from './modalState'
import { modalService } from './modalService'
import type { ModalButton } from './modal'

// 获取全局状态
const state = getModalState()

// 容器样式
const containerStyle = computed(() => ({
  width: typeof state.config.value.width === 'number' ? `${state.config.value.width}px` : state.config.value.width,
}))

// 检查是否有按钮正在加载
const isAnyButtonLoading = computed(() => {
  return state.config.value.buttons?.some((btn) => btn.loading) || false
})

// 关闭处理
const handleClose = () => {
  if (state.config.value.closable && !isAnyButtonLoading.value) {
    modalService.close()
  }
}

// 遮罩层点击
const handleOverlayClick = () => {
  if (state.config.value.maskClosable && !isAnyButtonLoading.value) {
    handleClose()
  }
}

// 按钮点击处理
const handleButtonClick = async (btn: ModalButton, index: number) => {
  if (btn.loading) return

  try {
    // 设置加载状态
    if (btn.onClick) {
      modalService.updateButtonLoading(index, true)

      // 执行点击回调
      const result = btn.onClick()

      // 如果是 Promise，等待完成
      if (result && typeof result.then === 'function') {
        await result
      }
    }

    // 自动关闭
    if (btn.autoClose !== false) {
      modalService.close()
    }
  } catch (error) {
    console.error('Modal button click error:', error)
  } finally {
    // 清除加载状态
    modalService.updateButtonLoading(index, false)
  }
}

// 动画结束后的清理
const handleAfterLeave = () => {
  // 重置配置，避免下次打开时显示旧内容
  state.config.value = {}
}

// 监听 ESC 键关闭
const handleKeydown = (event: KeyboardEvent) => {
  if (event.key === 'Escape' && state.visible.value && state.config.value.closable) {
    handleClose()
  }
}

// 添加/移除键盘事件监听
watch(
  () => state.visible.value,
  (visible) => {
    if (visible) {
      document.addEventListener('keydown', handleKeydown)
      document.body.style.overflow = 'hidden'
    } else {
      document.removeEventListener('keydown', handleKeydown)
      document.body.style.overflow = ''
    }
  },
  { immediate: true },
)
</script>

<style scoped>
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
  padding: 20px;
}

.modal-container {
  background: white;
  border-radius: 8px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
  max-width: 90vw;
  max-height: 90vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 24px;
  border-bottom: 1px solid #f0f0f0;
  flex-shrink: 0;
}

.modal-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #333;
}

.close-btn {
  background: none;
  border: none;
  font-size: 20px;
  cursor: pointer;
  padding: 4px;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  color: #999;
  transition: all 0.2s;
}

.close-btn:hover:not(:disabled) {
  background: #f5f5f5;
  color: #666;
}

.close-btn:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

.modal-content {
  padding: 24px;
  overflow: auto;
  flex: 1;
}

.modal-content.no-header {
  padding-top: 32px;
}

.modal-footer {
  padding: 20px 24px;
  border-top: 1px solid #f0f0f0;
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  flex-shrink: 0;
}

.btn {
  padding: 8px 16px;
  border: 1px solid #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  background: white;
  font-size: 14px;
  transition: all 0.2s;
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 60px;
  justify-content: center;
}

.btn:hover:not(:disabled) {
  border-color: #4096ff;
  color: #4096ff;
}

.btn:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

.btn-primary {
  background: #1890ff;
  border-color: #1890ff;
  color: white;
}

.btn-primary:hover:not(:disabled) {
  background: #4096ff;
  border-color: #4096ff;
  color: white;
}

.btn-danger {
  background: #ff4d4f;
  border-color: #ff4d4f;
  color: white;
}

.btn-danger:hover:not(:disabled) {
  background: #ff7875;
  border-color: #ff7875;
  color: white;
}

.btn-loading .btn-text {
  opacity: 0.7;
}

.btn-loading-spinner {
  width: 14px;
  height: 14px;
  border: 2px solid transparent;
  border-top: 2px solid currentColor;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* 过渡动画 */
.modal-enter-active,
.modal-leave-active {
  transition: all 0.3s ease;
}

.modal-enter-from {
  opacity: 0;
  transform: scale(0.9) translateY(-20px);
}

.modal-leave-to {
  opacity: 0;
  transform: scale(0.9) translateY(20px);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .modal-overlay {
    padding: 10px;
  }

  .modal-container {
    max-width: 95vw;
    max-height: 95vh;
  }

  .modal-header,
  .modal-content,
  .modal-footer {
    padding: 16px 20px;
  }

  .modal-footer {
    flex-direction: column-reverse;
  }

  .btn {
    width: 100%;
  }
}
</style>
